﻿#region Copyrights

/*
    - - - - - - - - - - - - - - - - - - - - - - -
    Nome do Arquivo : DAOHelper.cs
    - - - - - - - - - - - - - - - - - - - - - - -

    Sistema				    :  	LLS.Core
    Modulo				    :  	LLS.DataAccess.Core
    Autor				    :	Leonardo L. de Siqueira
    Data					:	27/02/2012
    Descrição  				:	Classe auxiliar para a manipulação / persistência de dados.
    
*/

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.Common;
using System.Data;

namespace LLS.DataAccess.Core
{
    /// <summary>
    /// Classe auxiliar para a manipulação / persistência de dados.
    /// </summary>
    public class DAOHelper
    {
        #region Constants

        private static readonly string _connectionString = ConfigurationManager.AppSettings["DATA.CONNECTIONSTRING"];
        private static readonly string _dataProvider = ConfigurationManager.AppSettings["DATA.PROVIDER"];

        #endregion

        #region Fields

        private DbProviderFactory _dbProviderFactory;
        private DbConnection _dbConnection;
        private DbCommand _dbCommand;
        private DbParameter _dbParameter;
        private DbTransaction _dbTransaction;
        private bool _isTransaction;

        #endregion

        #region Enumerators

        /// <summary>
        /// Enum com os tipos válidos de ações para transações
        /// </summary>
        public enum TransactionActionType : uint
        {
            /// <summary>
            /// Tipo para abertura da transação
            /// </summary>
            Begin = 1,
            /// <summary>
            /// Tipo para efetivar a transação
            /// </summary>
            Commit = 2,
            /// <summary>
            /// tipo para desfazer a transação
            /// </summary>
            Rollback = 3
        }

        #endregion

        #region Data Structures

        /// <summary>
        /// Estrutura de dados para armazenamento dos dados de um parâmetro
        /// </summary>
        public struct Parameter
        {
            /// <summary>
            /// Resgata / define o nome do parâmetro
            /// </summary>
            public string Name;

            /// <summary>
            /// Resgata / define o tipo do parâmetro
            /// </summary>
            public DbType Type;

            /// <summary>
            /// Resgata / define o tamanho do parâmetro
            /// </summary>
            public int Size;

            /// <summary>
            /// Resgata / define a direção do parâmetro
            /// </summary>
            public ParameterDirection Direction;

            /// <summary>
            /// Resgata / define o valor do parâmetro
            /// </summary>
            public object Value;

            /// <summary>
            /// Método construtor
            /// </summary>
            /// <param name="name">Nome do parâmetro</param>
            /// <param name="type">Tipo do parâmetro</param>
            /// <param name="size">Tamanho do parâmetro</param>
            /// <param name="direction">Direção do parâmetro</param>
            /// <param name="value">Valor do parâmetro</param>            
            public Parameter(string name, DbType type, int size, ParameterDirection direction, object value)
            {
                Name = name;
                Type = type;
                Size = size;
                Direction = direction;
                Value = value;
            }

            /// <summary>
            /// Método construtor
            /// </summary>
            /// <param name="name">Nome do parâmetro</param>
            /// <param name="type">Tipo do parâmetro</param>
            /// <param name="size">Tamanho do parâmetro</param>
            /// <param name="value">Valor do parâmetro</param>
            public Parameter(string name, DbType type, int size, object value)
            {
                Name = name;
                Type = type;
                Size = size;
                Direction = ParameterDirection.Input;
                Value = value;
            }
        }

        #endregion

        #region Methods

        #region Constructor

        /// <summary>
        /// Método construtor
        /// </summary>
        public DAOHelper()
        {
            _dbProviderFactory = DbProviderFactories.GetFactory(_dataProvider);
        }

        #endregion

        #region Destrutor

        /// <summary>
        /// Método destrutor
        /// </summary>
        ~DAOHelper()
        {
            _dbProviderFactory = null;
        }

        #endregion

        #region Connections

        /// <summary>
        /// Método para estabelecer uma conexão com o banco de dados
        /// </summary>
        public void EstablishFactoryConnection()
        {
            if (_dbConnection == null)
                _dbConnection = _dbProviderFactory.CreateConnection();

            if (_dbConnection.State == ConnectionState.Closed)
            {
                _dbConnection.ConnectionString = _connectionString;
                _dbConnection.Open();
            }
        }

        /// <summary>
        /// Método para fechar a conexão com o banco de dados
        /// </summary>
        public void CloseFactoryConnection()
        {
            //Verifica se a conexão está aberta         
            try
            {
                if (_dbConnection.State == ConnectionState.Open)
                    _dbConnection.Close();
            }
            catch (DbException ex)
            {
                //captura qualquer erro gerado pelo provider
                throw new Exception(ex.Message);
            }
            catch (System.NullReferenceException ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if (_dbConnection != null)
                    _dbConnection.Dispose();
            }
        }

        #endregion

        #region Transaction

        /// <summary>
        /// Método para tratar as ações para transações
        /// </summary>
        /// <param name="transactionActionType">Tipo de transação</param>
        public void TransactionHandler(TransactionActionType transactionActionType)
        {
            switch (transactionActionType)
            {
                case TransactionActionType.Begin:  //abre uma transação
                    try
                    {
                        _dbTransaction = _dbConnection.BeginTransaction();
                        _isTransaction = true;
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new Exception("@TransactionHandler - " + ex.Message);
                    }
                    break;

                case TransactionActionType.Commit:  //efetiva a transação
                    if (_dbTransaction.Connection != null)
                    {
                        try
                        {
                            _dbTransaction.Commit();
                            _isTransaction = false;
                        }
                        catch (InvalidOperationException ex)
                        {
                            throw new Exception("@TransactionHandler - " + ex.Message);
                        }
                    }
                    break;

                case TransactionActionType.Rollback:  //desfaz a transação
                    try
                    {
                        if (_isTransaction)
                            _dbTransaction.Rollback();

                        _isTransaction = false;
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new Exception("@TransactionHandler - " + ex.Message);
                    }
                    break;
            }
        }

        #endregion

        #region Commands

        #region Parameterless methods

        /// <summary>
        /// Método para preparar os comandos para execução
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        private void PrepareCommand(bool isTransaction, CommandType commandType, string commandText)
        {
            if (_dbConnection.State != ConnectionState.Open)
            {
                _dbConnection.ConnectionString = _connectionString;
                _dbConnection.Open();
            }

            if (_dbCommand != null)
                _dbCommand = _dbProviderFactory.CreateCommand();

            _dbCommand.Connection = _dbConnection;
            _dbCommand.CommandType = commandType;
            _dbCommand.CommandText = commandText;

            if (isTransaction)
                _dbCommand.Transaction = _dbTransaction;
        }

        #endregion

        #region Object based parameter array methods

        /// <summary>
        /// Método para preparar os comandos para execução
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        private void PrepareCommand(bool isTransaction, CommandType commandType, string commandText, object[,] parameters)
        {
            if (_dbConnection.State != ConnectionState.Open)
            {
                _dbConnection.ConnectionString = _connectionString;
                _dbConnection.Open();
            }

            if (_dbCommand != null)
                _dbCommand = _dbProviderFactory.CreateCommand();

            _dbCommand.Connection = _dbConnection;
            _dbCommand.CommandType = commandType;
            _dbCommand.CommandText = commandText;

            if (isTransaction)
                _dbCommand.Transaction = _dbTransaction;

            if (parameters != null)
                CreateDBParameters(parameters);
        }

        #endregion

        #region Structure based parameter array methods

        /// <summary>
        /// Método para preparar os comandos para execução
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        private void PrepareCommand(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters)
        {
            if (_dbConnection.State != ConnectionState.Open)
            {
                _dbConnection.ConnectionString = _connectionString;
                _dbConnection.Open();
            }

            if (_dbCommand == null)
                _dbCommand = _dbProviderFactory.CreateCommand();

            _dbCommand.Connection = _dbConnection;
            _dbCommand.CommandType = commandType;
            _dbCommand.CommandText = commandText;

            if (isTransaction)
                _dbCommand.Transaction = _dbTransaction;

            if (parameters != null)
                CreateDBParameters(parameters);
        }

        #endregion

        #endregion

        #region Parameters

        #region Object based parameter array methods

        /// <summary>
        /// Método para a criação dos parâmetros para o comando a ser executado
        /// </summary>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        private void CreateDBParameters(object[,] parameters)
        {
            for (int i = 0; i < parameters.Length / 2; i++)
            {
                _dbParameter = _dbCommand.CreateParameter();
                _dbParameter.ParameterName = parameters[i, 0].ToString();
                _dbParameter.DbType = (DbType)parameters[i, 1];
                _dbParameter.Size = (int)parameters[i, 2];
                _dbParameter.SourceColumnNullMapping = (bool)parameters[i, 3];
                _dbParameter.Direction = (ParameterDirection)parameters[i, 4];
                _dbParameter.Value = parameters[i, 5];
                _dbCommand.Parameters.Add(_dbParameter);
            }
        }

        #endregion

        #region Métodos com parâmetros do tipo array de estruturas de dados

        /// <summary>
        /// Método para a criação dos parâmetros para o comando a ser executado
        /// </summary>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        private void CreateDBParameters(Parameter[] parameters)
        {
            for (int i = 0; i < parameters.Length; i++)
            {
                Parameter parameter = (Parameter)parameters[i];

                _dbParameter = _dbCommand.CreateParameter();
                _dbParameter.ParameterName = parameter.Name;
                _dbParameter.DbType = parameter.Type;
                _dbParameter.Size = parameter.Size;
                _dbParameter.Direction = parameter.Direction;
                _dbParameter.Value = parameter.Value;
                _dbCommand.Parameters.Add(_dbParameter);
            }
        }

        #endregion

        #endregion

        #region Execute

        #region Parameterless methods

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(CommandType commandType, string commandText)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText);
                return _dbCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(bool isTransaction, CommandType commandType, string commandText)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText);
                int val = _dbCommand.ExecuteNonQuery();
                return val;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Object based parameter array methods

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteNonQuery(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                return _dbCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(bool isTransaction, CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteNonQuery(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(bool isTransaction, CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                return _dbCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Structure based parameter array methods

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(CommandType commandType, string commandText, Parameter[] parameters)
        {
            return ExecuteNonQuery(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                return _dbCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters)
        {
            return ExecuteNonQuery(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para a execução de um comando
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Número de linhas afetadas</returns>
        public int ExecuteNonQuery(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                return _dbCommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #endregion

        #region Reader

        #region Parameterless methods

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(CommandType commandType, string commandText)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText);
                DbDataReader dr = _dbCommand.ExecuteReader();
                _dbCommand.Parameters.Clear();
                return dr;
            }
            catch (Exception ex)
            {
                CloseFactoryConnection();
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(bool isTransaction, CommandType commandType, string commandText)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText);
                DbDataReader dr = _dbCommand.ExecuteReader();
                _dbCommand.Parameters.Clear();
                return dr;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Object based parameter array methods

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteReader(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                DbDataReader dr = _dbCommand.ExecuteReader();
                return dr;
            }
            catch (Exception ex)
            {
                CloseFactoryConnection();
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(bool isTransaction, CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteReader(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(bool isTransaction, CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                DbDataReader dr = _dbCommand.ExecuteReader();
                return dr;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Structure based parameter array methods

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(CommandType commandType, string commandText, Parameter[] parameters)
        {
            return ExecuteReader(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                return _dbCommand.ExecuteReader();
            }
            catch (Exception ex)
            {
                CloseFactoryConnection();
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters)
        {
            return ExecuteReader(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataReader
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataReader</returns>
        public DbDataReader ExecuteReader(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                return _dbCommand.ExecuteReader();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #endregion

        #region Adapter

        #region Parameterless methods

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(CommandType commandType, string commandText)
        {
            DbDataAdapter dda = null;

            try
            {
                EstablishFactoryConnection();
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(false, commandType, commandText);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(bool isTransaction, CommandType commandType, string commandText)
        {
            DbDataAdapter dda = null;

            try
            {
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(isTransaction, commandType, commandText);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Object based parameter array methods

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(CommandType commandType, string commandText, object[,] parameters)
        {
            return DataAdapter(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            DbDataAdapter dda = null;

            try
            {
                EstablishFactoryConnection();
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(false, commandType, commandText, parameters);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(bool isTransaction, CommandType commandType, string commandText, object[,] parameters)
        {
            return DataAdapter(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(bool isTransaction, CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            DbDataAdapter dda = null;

            try
            {
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Structure based parameter array methods

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(CommandType commandType, string commandText, Parameter[] parameters)
        {
            return DataAdapter(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            DbDataAdapter dda = null;

            try
            {
                EstablishFactoryConnection();
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(false, commandType, commandText, parameters);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters)
        {
            return DataAdapter(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método para leitura de dados através de um DataAdapter
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>DataSet</returns>
        public DataSet DataAdapter(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            DbDataAdapter dda = null;

            try
            {
                dda = _dbProviderFactory.CreateDataAdapter();
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                dda.SelectCommand = _dbCommand;
                DataSet ds = new DataSet();
                dda.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #endregion

        #region Scalar

        #region Parameterless methods

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(CommandType commandType, string commandText)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText);
                object val = _dbCommand.ExecuteScalar();
                return val;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(bool isTransaction, CommandType commandType, string commandText)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText);
                object val = _dbCommand.ExecuteScalar();
                return val;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Object based parameter array methods

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteScalar(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                return _dbCommand.ExecuteScalar();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(bool isTransaction, CommandType commandType, string commandText, object[,] parameters)
        {
            return ExecuteScalar(isTransaction, commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array bidimensional do tipo object com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(bool isTransaction, CommandType commandType, string commandText, object[,] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                return _dbCommand.ExecuteScalar();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #region Structure based parameter array methods

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(CommandType commandType, string commandText, Parameter[] parameters)
        {
            return ExecuteScalar(commandType, commandText, parameters, true);
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                EstablishFactoryConnection();
                PrepareCommand(false, commandType, commandText, parameters);
                return _dbCommand.ExecuteScalar();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }

                CloseFactoryConnection();
            }
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="textoDoComando">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(bool isTransaction, CommandType commandType, string textoDoComando, Parameter[] parameters)
        {
            return ExecuteScalar(isTransaction, commandType, textoDoComando, parameters, true);
        }

        /// <summary>
        /// Método responsável pela execução de comandos escalares
        /// </summary>
        /// <param name="isTransaction">Define se os comandos serão executados em uma transação</param>
        /// <param name="commandType">Tipo do comando</param>
        /// <param name="commandText">Texto do comando</param>
        /// <param name="parameters">Array do tipo Parameter com os parâmetros do comando</param>
        /// <param name="isDisposeCommand">Define se os comandos serão destruidos após a execução</param>
        /// <returns>Object</returns>
        public object ExecuteScalar(bool isTransaction, CommandType commandType, string commandText, Parameter[] parameters, bool isDisposeCommand)
        {
            try
            {
                PrepareCommand(isTransaction, commandType, commandText, parameters);
                return _dbCommand.ExecuteScalar();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (isDisposeCommand && _dbCommand != null)
                {
                    _dbCommand.Dispose();
                    _dbCommand = null;
                }
            }
        }

        #endregion

        #endregion

        #endregion
    }
}
